import 'dart:ui' as dartUi;

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

import '../extentions/ui_extentions.dart';

class CustomTextField extends StatelessWidget {
  final TextField textField;
  final double customPaddingRight;
  final bool customHasDivider;
  final double customLabelPaddingTop;
  final InputDecoration decoration;

  CustomTextField({
    Key? key,
    TextEditingController? controller,
    FocusNode? focusNode,
    this.decoration = const InputDecoration(),
    TextInputType? keyboardType,
    TextInputAction? textInputAction,
    TextCapitalization textCapitalization = TextCapitalization.none,
    TextStyle? style,
    StrutStyle? strutStyle,
    TextAlign textAlign = TextAlign.end,
    TextAlignVertical? textAlignVertical,
    TextDirection? textDirection,
    bool readOnly = false,
    ToolbarOptions? toolbarOptions,
    bool? showCursor,
    bool autofocus = false,
    bool obscureText = false,
    bool autocorrect = true,
    SmartDashesType? smartDashesType,
    SmartQuotesType? smartQuotesType,
    bool enableSuggestions = true,
    int maxLines = 1,
    int? minLines,
    bool expands = false,
    int? maxLength,
    bool maxLengthEnforced = true,
    ValueChanged<String>? onChanged,
    VoidCallback? onEditingComplete,
    ValueChanged<String>? onSubmitted,
    List<TextInputFormatter>? inputFormatters,
    bool? enabled,
    double cursorWidth = 2.0,
    Radius? cursorRadius,
    Color? cursorColor,
    dartUi.BoxHeightStyle selectionHeightStyle = dartUi.BoxHeightStyle.tight,
    dartUi.BoxWidthStyle selectionWidthStyle = dartUi.BoxWidthStyle.tight,
    Brightness? keyboardAppearance,
    EdgeInsets scrollPadding = const EdgeInsets.all(20.0),
    DragStartBehavior dragStartBehavior = DragStartBehavior.start,
    bool enableInteractiveSelection = true,
    GestureTapCallback? onTap,
    InputCounterWidgetBuilder? buildCounter,
    ScrollController? scrollController,
    ScrollPhysics? scrollPhysics,
    this.customPaddingRight = 0.0,
    this.customHasDivider = true,
    this.customLabelPaddingTop = 16.0,
  }) : textField = TextField(
          key: key,
          controller: controller,
          focusNode: focusNode,
          decoration: _customInputDecoration(
            decoration,
            customPaddingRight,
            customHasDivider,
          ),
          keyboardType: keyboardType,
          textInputAction: textInputAction,
          textCapitalization: textCapitalization,
          style: style,
          strutStyle: strutStyle,
          textAlign: textAlign,
          textAlignVertical: textAlignVertical,
          textDirection: textDirection,
          readOnly: readOnly,
          toolbarOptions: toolbarOptions,
          showCursor: showCursor,
          autofocus: autofocus,
          obscureText: obscureText,
          autocorrect: autocorrect,
          smartDashesType: smartDashesType,
          smartQuotesType: smartQuotesType,
          enableSuggestions: enableSuggestions,
          maxLines: maxLines,
          minLines: minLines,
          expands: expands,
          maxLength: maxLength,
          onChanged: onChanged,
          onEditingComplete: onEditingComplete,
          onSubmitted: onSubmitted,
          inputFormatters: inputFormatters,
          enabled: enabled,
          cursorWidth: cursorWidth,
          cursorRadius: cursorRadius,
          cursorColor: cursorColor,
          selectionHeightStyle: selectionHeightStyle,
          selectionWidthStyle: selectionWidthStyle,
          keyboardAppearance: keyboardAppearance,
          scrollPadding: scrollPadding,
          dragStartBehavior: dragStartBehavior,
          enableInteractiveSelection: enableInteractiveSelection,
          onTap: onTap,
          buildCounter: buildCounter,
          scrollController: scrollController,
          scrollPhysics: scrollPhysics,
        );

  @override
  Widget build(BuildContext context) {
    bool hasLabel = decoration.labelText?.isNotEmpty ?? false;
    bool hasSuffixText = decoration.suffixText?.isNotEmpty ?? false;
    bool? required = decoration.labelText?.contains("*");
    if (hasLabel) {
      return Stack(
        children: <Widget>[
          textField,
          Positioned(
            left: 0,
            right: 0,
            top: this.customLabelPaddingTop,
            child: Row(
              children: <Widget>[
                Text(
                  decoration.labelText?.replaceFirst("*", "") ?? "",
                  style: textField.decoration?.labelStyle,
                ),
                if (required!)
                  Padding(
                    padding: const EdgeInsets.only(top: 4),
                    child: RequiredIndicatorWidget(),
                  ),
                Spacer(),
                if (hasSuffixText)
                  Text(
                    decoration.suffixText!,
                    style: decoration
                        .suffixStyle /*?? defaultTextFieldLabelStyle*/,
                  ),
                if (decoration.suffix != null) decoration.suffix!,
              ],
            ),
          ),
        ],
      );
    } else {
      return textField;
    }
  }
}

class CustomTextFormField extends StatelessWidget {
  final TextFormField textFormField;
  final InputDecoration decoration;

  final double customPaddingRight;
  final bool customHasDivider;
  final double customLabelPaddingTop;

  CustomTextFormField({
    Key? key,
    TextEditingController? controller,
    String? initialValue,
    FocusNode? focusNode,
    this.decoration = const InputDecoration(),
    TextInputType? keyboardType,
    TextCapitalization textCapitalization = TextCapitalization.none,
    TextInputAction? textInputAction,
    TextStyle? style/*= defaultTextFieldTextStyle*/,
    StrutStyle? strutStyle,
    TextDirection? textDirection,
    TextAlign textAlign = TextAlign.end,
    TextAlignVertical? textAlignVertical,
    bool autofocus = false,
    bool readOnly = false,
    ToolbarOptions? toolbarOptions,
    bool? showCursor,
    bool obscureText = false,
    bool autocorrect = true,
    SmartDashesType? smartDashesType,
    SmartQuotesType? smartQuotesType,
    bool enableSuggestions = true,
    AutovalidateMode autovalidateMode = AutovalidateMode.onUserInteraction,
    bool maxLengthEnforced = true,
    int maxLines = 1,
    int? minLines,
    bool expands = false,
    int? maxLength,
    ValueChanged<String>? onChanged,
    GestureTapCallback? onTap,
    VoidCallback? onEditingComplete,
    ValueChanged<String>? onFieldSubmitted,
    FormFieldSetter<String>? onSaved,
    FormFieldValidator<String>? validator,
    List<TextInputFormatter>? inputFormatters,
    bool enabled = true,
    double cursorWidth = 2.0,
    Radius? cursorRadius,
    Color? cursorColor,
    Brightness? keyboardAppearance,
    EdgeInsets scrollPadding = const EdgeInsets.all(20.0),
    bool enableInteractiveSelection = true,
    InputCounterWidgetBuilder? buildCounter,
    ScrollPhysics? scrollPhysics,
    this.customPaddingRight = 0.0,
    this.customHasDivider = true,
    this.customLabelPaddingTop = 16.0,
  }) : textFormField = TextFormField(
          key: key,
          controller: controller,
          initialValue: initialValue,
          focusNode: focusNode,
          decoration: _customInputDecoration(
            decoration,
            customPaddingRight,
            customHasDivider,
          ),
          keyboardType: keyboardType,
          textCapitalization: textCapitalization,
          textInputAction: textInputAction,
          style: style,
          strutStyle: strutStyle,
          textDirection: textDirection,
          textAlign: textAlign,
          textAlignVertical: textAlignVertical,
          autofocus: autofocus,
          readOnly: readOnly,
          toolbarOptions: toolbarOptions,
          showCursor: showCursor,
          obscureText: obscureText,
          autocorrect: autocorrect,
          smartDashesType: smartDashesType,
          smartQuotesType: smartQuotesType,
          enableSuggestions: enableSuggestions,
          autovalidateMode: autovalidateMode,
          maxLines: maxLines,
          minLines: minLines,
          expands: expands,
          maxLength: maxLength,
          onChanged: onChanged,
          onTap: onTap,
          onEditingComplete: onEditingComplete,
          onFieldSubmitted: onFieldSubmitted,
          onSaved: onSaved,
          validator: validator,
          inputFormatters: inputFormatters,
          enabled: enabled,
          cursorWidth: cursorWidth,
          cursorRadius: cursorRadius,
          cursorColor: cursorColor,
          keyboardAppearance: keyboardAppearance,
          scrollPadding: scrollPadding,
          enableInteractiveSelection: enableInteractiveSelection,
          buildCounter: buildCounter,
          scrollPhysics: scrollPhysics,
        );

  @override
  Widget build(BuildContext context) {
    bool hasLabel = decoration.labelText?.isNotEmpty ?? false;
    bool hasSuffixText = decoration.suffixText?.isNotEmpty ?? false;
    bool? required = decoration.labelText?.contains("*");
    if (hasLabel) {
      return Stack(
        children: <Widget>[
          textFormField,
          Positioned(
            left: 0,
            right: 0,
            top: customLabelPaddingTop,
            child: Row(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                Text(
                  decoration.labelText?.replaceFirst("*", "") ?? "",
                  style: decoration.labelStyle,
                ),
                if (required!)
                  Padding(
                    padding: const EdgeInsets.only(top: 4.0),
                    child: RequiredIndicatorWidget(),
                  ),
                Spacer(),
                if (hasSuffixText)
                  Text(
                    decoration.suffixText!,
                    style: decoration.suffixStyle,
                  ),
                if (decoration.suffix != null) decoration.suffix!,
              ],
            ),
          ),
        ],
      );
    } else {
      return textFormField;
    }
  }
}

InputDecoration _customInputDecoration(
  InputDecoration decoration,
  double customPaddingRight,
  bool customHasDivider,
) {
  bool hasLabel = decoration.labelText?.isNotEmpty ?? false;
  if (!hasLabel) return decoration;
  final paddingLeft =
      (decoration.labelStyle ?? TextStyle()).displayWidth(decoration.labelText);
  final paddingRight = (decoration.suffixStyle ?? TextStyle())
      .displayWidth(decoration.suffixText);
  final hasSuffix = decoration.suffix != null;
  double paddingRightExtra = customPaddingRight;
  if (hasSuffix && paddingRightExtra < 1) {
    paddingRightExtra = 16.0;
  }
  return decoration.copyWithNull(
    labelText: null,
    suffixText: null,
    suffix: null,
    suffixStyle: decoration.suffixStyle /*?? defaultTextFieldLabelStyle*/,
    hintText: decoration.hintText ?? "请输入",
//    hintStyle: Ui.textFieldHintStyle,
    labelStyle: decoration.labelStyle /*?? Ui.defaultLabelStyle*/,
    contentPadding: EdgeInsets.only(
      right: paddingRight + paddingRightExtra,
      top: 16,
      bottom: 16,
      left: paddingLeft + 4.0,
    ),
    enabledBorder: customHasDivider == true ? null : InputBorder.none,
    disabledBorder: customHasDivider == true ? null : InputBorder.none,
  );
}

extension on InputDecoration {
  InputDecoration copyWithNull({
    Widget? icon,
    String? labelText,
    TextStyle? labelStyle,
    String? helperText,
    TextStyle? helperStyle,
    int? helperMaxLines,
    String? hintText,
    TextStyle? hintStyle,
    int? hintMaxLines,
    String? errorText,
    TextStyle? errorStyle,
    int? errorMaxLines,
    FloatingLabelBehavior? floatingLabelBehavior,
    bool? isDense,
    EdgeInsetsGeometry? contentPadding,
    Widget? prefixIcon,
    Widget? prefix,
    String? prefixText,
    BoxConstraints? prefixIconConstraints,
    TextStyle? prefixStyle,
    Widget? suffixIcon,
    Widget? suffix,
    String? suffixText,
    TextStyle? suffixStyle,
    BoxConstraints? suffixIconConstraints,
    Widget? counter,
    String? counterText,
    TextStyle? counterStyle,
    bool? filled,
    Color? fillColor,
    Color? focusColor,
    Color? hoverColor,
    InputBorder? errorBorder,
    InputBorder? focusedBorder,
    InputBorder? focusedErrorBorder,
    InputBorder? disabledBorder,
    InputBorder? enabledBorder,
    InputBorder? border,
    bool? enabled,
    String? semanticCounterText,
    bool? alignLabelWithHint,
  }) {
    return InputDecoration(
      icon: icon ?? this.icon,
      labelText: labelText,
      labelStyle: labelStyle ?? this.labelStyle,
      helperText: helperText ?? this.helperText,
      helperStyle: helperStyle ?? this.helperStyle,
      helperMaxLines: helperMaxLines ?? this.helperMaxLines,
      hintText: hintText ?? this.hintText,
      hintStyle: hintStyle ?? this.hintStyle,
      hintMaxLines: hintMaxLines ?? this.hintMaxLines,
      errorText: errorText ?? this.errorText,
      errorStyle: errorStyle ?? this.errorStyle,
      errorMaxLines: errorMaxLines ?? this.errorMaxLines,
      floatingLabelBehavior:
          floatingLabelBehavior ?? this.floatingLabelBehavior,
      isDense: isDense ?? this.isDense,
      contentPadding: contentPadding ?? this.contentPadding,
      prefixIcon: prefixIcon ?? this.prefixIcon,
      prefix: prefix ?? this.prefix,
      prefixText: prefixText ?? this.prefixText,
      prefixStyle: prefixStyle ?? this.prefixStyle,
      prefixIconConstraints:
          prefixIconConstraints ?? this.prefixIconConstraints,
      suffixIcon: suffixIcon ?? this.suffixIcon,
      suffix: suffix,
      suffixText: suffixText,
      suffixStyle: suffixStyle ?? this.suffixStyle,
      suffixIconConstraints:
          suffixIconConstraints ?? this.suffixIconConstraints,
      counter: counter ?? this.counter,
      counterText: counterText ?? this.counterText,
      counterStyle: counterStyle ?? this.counterStyle,
      filled: filled ?? this.filled,
      fillColor: fillColor ?? this.fillColor,
      focusColor: focusColor ?? this.focusColor,
      hoverColor: hoverColor ?? this.hoverColor,
      errorBorder: errorBorder ?? this.errorBorder,
      focusedBorder: focusedBorder ?? this.focusedBorder,
      focusedErrorBorder: focusedErrorBorder ?? this.focusedErrorBorder,
      disabledBorder: disabledBorder ?? this.disabledBorder,
      enabledBorder: enabledBorder ?? this.enabledBorder,
      border: border ?? this.border,
      enabled: enabled ?? this.enabled,
      semanticCounterText: semanticCounterText ?? this.semanticCounterText,
      alignLabelWithHint: alignLabelWithHint ?? this.alignLabelWithHint,
    );
  }
}

class RequiredIndicatorWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Text(
      "*",
      style: const TextStyle(
        fontSize: 20,
        color: Colors.red,
      ),
    );
  }
}
